const Route = require('./route');
const Layer = require('./layer');
const url = require('url');
const methods = require('methods');
function Router() {
    const router = (req, res, next) => {
        // 交给当前去处理
        router.handle(req, res, next);
    }
    router.stack = [];
    router.__proto__ = proto;
    // 兼容new Router()和Router() 两种情况
    return router;
}

const proto = {};
proto.route = function (path) {
    // 为每个方法(get post put delete等)创建一个层
    const route = new Route(path);
    const layer = new Layer(path, route.dispatch.bind(route));
    // layer能找到当前的路由，标识是路由
    layer.route = route;
    this.stack.push(layer);
    return route
}

methods.forEach(method => {
    proto[method] = function (path, handles) {
        let route = this.route(path);
        // 往当前路由添加处理函数
        route[method](handles);
    }
})
proto.paramsCallback = [];

proto.handle_param = function (layer, req, res, out) {
    if (layer.keys.length === 0) {
        return out();
    }
    // 如果layer.keys有传入的param的key才执行，否则不执行
    const keys = Object.keys(req.params);
    let index = 0;
    let handles;
    let key;
    let next = () => {
        if (index === keys.length) {
            return out();
        }
        key = keys[index++];
        handles = this.paramsCallback[key];
        // console.log(handles, key, req.params[key]);
        if (handles) {
            resolveHandle(handles, key, req.params[key], next);
        }
    }
    let i = 0;
    let resolveHandle = () => {
        if (i === handles.length) {
            // 清零，轮到下一个是从头开始
            i = 0;
            return next();
        }
        const handle = handles[i++];
        if (handle) {
            handle(req, res, resolveHandle, req.params[key], key)
        }
    }
    next();
}
proto.handle = function (req, res, out) {
    const { pathname } = url.parse(req.url);
    let index = 0;
    let remove = '';
    const next = (err) => {
        if (index === this.stack.length) return out();
        // 出来了要重新拼接上,进去是删除
        // 正常的use也没有关系
        if (remove) {
            req.url = remove + req.url;
            remove = "";
        }
        const layer = this.stack[index++];
        if (err) { // 有错误
            if (layer.route) {
                next(err);// 是路由，传递给下一个中间件
            } else {
                return layer.handle_err(err, req, res, next);
            }
        } else {
            if (layer.match(pathname)) {
                if (layer.params) {
                    req.params = layer.params;
                }
                // 是路由
                if (layer.route) {
                    if (layer.route.methods[req.method.toLowerCase()]) {
                        console.log('-------------------------------------');
                        // 先处理param,完了在处理匹配
                        // 传layer是为了获得请求参数上的key
                        proto.handle_param(layer, req, res, () => {
                            layer.handle_request(req, res, next);
                        })
                    } else {
                        next();
                    }
                } else if (layer.handler.length !== 4) { // 是中间件，并且不是错误处理use中间件  直接执行
                    if (layer.path !== '/') {
                        remove = layer.path;
                        //要将这样 /user/add => req.url = /add
                        req.url = pathname.slice(remove.length);
                    }
                    layer.handle_request(req, res, next);
                }
            } else {
                next();
            }
        }
    }
    next();
}

proto.use = function (path, handle) {
    // console.log(path, handle);
    if (typeof path === 'function') {
        handle = path;
        // 不传path, 默认是/
        path = '/';
    }
    const layer = new Layer(path, handle);
    layer.route = undefined; // 标记不是路由，是中间件
    this.stack.push(layer);
}

proto.param = function (key, handle) {
    const paramsCallback = this.paramsCallback;
    // [name: [fn, fn], ...] 一个Key对应多个函数
    (paramsCallback[key] || (paramsCallback[key] = [])).push(handle);
}

module.exports = Router;